package com.xz.stu.server.service.impl;

import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApi;
import cn.iocoder.yudao.module.system.api.notify.dto.NotifySendSingleToUserReqDTO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.UserRoleDO;
import cn.iocoder.yudao.module.system.dal.mysql.permission.RoleMapper;
import cn.iocoder.yudao.module.system.dal.mysql.permission.UserRoleMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xz.stu.server.entity.Term;
import com.xz.stu.server.job.DynamicScheduledTask;
import com.xz.stu.server.mapper.CalendarEventMapper;
import com.xz.stu.server.service.CalendarEventService;
import com.xz.stu.server.service.TermService;
import com.xz.stu.server.vo.calenderEvent.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xz.stu.server.entity.CalendarEvent;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
* @author 熊磊
* @description 针对表【school_calendar_event(校历事件表)】的数据库操作Service实现
* @createDate 2025-02-26 15:34:32
*/
@Service
public class CalendarEventServiceImpl extends ServiceImpl<CalendarEventMapper, CalendarEvent>
    implements CalendarEventService {
    @Resource
    private TermService termService;
    @Resource
    private UserRoleMapper userRoleMapper;
    @Resource
    private RoleMapper roleMapper;
    @Resource
    private DynamicScheduledTask dynamicScheduledTask;
    @Resource
    private NotifyMessageSendApi notifySendApi;

    @Override
    public Long createEvent(CalendarEventCreateReqVO createReqVO) {
        CalendarEvent calendarEvent = BeanUtils.toBean(createReqVO, CalendarEvent.class);
        Term one = termService.lambdaQuery()
                .eq(Term::getTermCode, createReqVO.getTermCode())
                .one();
        calendarEvent.setTermId(one.getId());
        //获取用户Id
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        if (loginUser != null) {
            calendarEvent.setUsers(String.valueOf(loginUser.getId()));
        }
        this.save(calendarEvent);
        extracted(calendarEvent);
        return calendarEvent.getId();
    }

    private void extracted(CalendarEvent calendarEvent) {
        //加入定时任务
        Runnable task = () -> {
            //判断事件日期是否超过当前时间
            if (calendarEvent.getEventDate().isBefore(LocalDateTime.now())) {
                dynamicScheduledTask.removeTask(String.valueOf(calendarEvent.getId()));
                return;
            }
            DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            NotifySendSingleToUserReqDTO reqDTO = new NotifySendSingleToUserReqDTO();
            reqDTO.setTemplateCode("notice"); // 设置消息内容
            HashMap<String, Object> map = new HashMap<>();
            map.put("eventDate", df.format(calendarEvent.getEventDate()));
            map.put("title", calendarEvent.getTitle());
            map.put("remark", calendarEvent.getRemark());
            reqDTO.setTemplateParams(map);
            String[] split = calendarEvent.getUsers().split(",");
            for (String s : split) {
                reqDTO.setUserId(Long.valueOf(s));
                notifySendApi.sendSingleMessageToAdmin(reqDTO);
            }
        };
        // 修改为 6 个字段的 Cron 表达式
        String validCronExpression = calendarEvent.getCron().split(" ").length == 7
                ? String.join(" ", Arrays.copyOf(calendarEvent.getCron().split(" "), 6))
                : calendarEvent.getCron();
        dynamicScheduledTask.addTask(String.valueOf(calendarEvent.getId()),validCronExpression , task);
    }

    @Override
    public void updateEvent(CalendarEventUpdateReqVO updateReqVO) {
        CalendarEvent calendarEvent = BeanUtils.toBean(updateReqVO, CalendarEvent.class);
        this.updateById(calendarEvent);
        extracted(calendarEvent);
    }

    @Override
    public void deleteEvent(List<Long> id) {
        this.removeByIds(id);
        //判断是否有定时任务
        for (Long aLong : id) {
            if (dynamicScheduledTask.isTaskExists(String.valueOf(aLong))) {
                dynamicScheduledTask.removeTask(String.valueOf(aLong));
            }
        }
    }

    @Override
    public CalendarEventRespVO getEvent(Long id) {
        CalendarEvent calendarEvent = this.getById(id);
        if (calendarEvent != null) {
            CalendarEventRespVO eventRespVO = BeanUtils.toBean(calendarEvent, CalendarEventRespVO.class);
            eventRespVO.setTermCode(termService.lambdaQuery().eq(Term::getId, calendarEvent.getTermId()).one().getTermCode());
            return eventRespVO;
        }
        throw new RuntimeException("事件不存在");
    }

    @Override
    public List<CalendarEventRespVO> getEventList(CalendarEventListReqVO listReqVO) {
        Term one = termService.lambdaQuery()
                .eq(Term::getTermCode, listReqVO.getTermCode())
                .one();
        //非管理员只能获取自己创建的事件和管理员创建的事件
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        List<RoleDO> roleDOS = roleMapper.selectList(RoleDO::getName, Arrays.asList("管理员", "超级管理员"));
        List<Long> userRoleDOS = userRoleMapper.selectList(UserRoleDO::getRoleId, roleDOS.stream().map(RoleDO::getId).collect(Collectors.toList()))
                .stream().map(UserRoleDO::getUserId).collect(Collectors.toList());

        if (loginUser != null) {
            userRoleDOS.add(loginUser.getId());
        }
        List<CalendarEventRespVO> calendarEventRespVOList = this.lambdaQuery()
                .between(CalendarEvent::getEventDate, listReqVO.getStartDate(), listReqVO.getEndDate())
                .in(CalendarEvent::getCreator, userRoleDOS)
                .list()
                .stream()
                .map(calendarEvent -> BeanUtils.toBean(calendarEvent, CalendarEventRespVO.class))
                .collect(Collectors.toList());
        calendarEventRespVOList.forEach(calendarEventRespVO -> {
            calendarEventRespVO.setTermCode(one.getTermCode());
        });
        return calendarEventRespVOList;
    }

    @Override
    public PageResult<CalendarEventRespVO> getEventLisPage(CalendarEventListPageReqVO listReqVO) {
        Long termId = null;
        if (Objects.nonNull(listReqVO.getTermCode())){
            Term one = termService.lambdaQuery()
                    .eq(Term::getTermCode, listReqVO.getTermCode())
                    .one();
            termId = one.getId();
        }
        //只能获取自己创建的事件
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        LambdaQueryWrapper<CalendarEvent> lambdaQueryWrapper = null;
        lambdaQueryWrapper = new LambdaQueryWrapper<CalendarEvent>()
                .eq(Objects.nonNull(listReqVO.getEventType()), CalendarEvent::getEventType, listReqVO.getEventType())
                .like(Objects.nonNull(listReqVO.getTitle()), CalendarEvent::getTitle, listReqVO.getTitle())
                .eq(!Objects.isNull(termId), CalendarEvent::getTermId, termId)
                .orderBy(Objects.nonNull(listReqVO.getIsAsc()), listReqVO.getIsAsc(), CalendarEvent::getEventDate)
                .between(Objects.nonNull(listReqVO.getStartDate()) && Objects.nonNull(listReqVO.getEndDate())
                        , CalendarEvent::getEventDate, listReqVO.getStartDate(), listReqVO.getEndDate());
        if (loginUser != null) {
            lambdaQueryWrapper.eq(CalendarEvent::getCreator, loginUser.getId());
        }
        Page<CalendarEvent> page = this.page(new Page<>(listReqVO.getPageNo(), listReqVO.getPageSize()), lambdaQueryWrapper);
        if (page != null) {
            Map<Long, String> stringMap = termService.list().stream().collect(Collectors.toMap(Term::getId, Term::getTermCode));
            PageResult<CalendarEventRespVO> pageResult = new PageResult<>(BeanUtils.toBean(page.getRecords(), CalendarEventRespVO.class), page.getTotal());
            pageResult.getList().forEach(calendarEventRespVO -> {
                calendarEventRespVO.setTermCode(stringMap.get(calendarEventRespVO.getTermId()));
            });
            return pageResult;
        }
        return null;
    }
}




